#include "remote_upgrade.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <signal.h>

// 信号处理
static volatile bool g_interrupted = false;
zlog_category_t *     neuron            = NULL;

static void signal_handler(int sig)
{
    printf("Received signal %d, shutting down...\n", sig);
    g_interrupted = true;
}

// 显示使用帮助
static void print_usage(const char* program_name)
{
    printf("Usage: %s [OPTIONS]\n", program_name);
    printf("Neuron Remote Upgrade Tool\n\n");
    printf("Required options:\n");
    printf("  -b, --broker HOST        MQTT broker hostname or IP\n");
    printf("  -u, --url URL            Upgrade package download URL\n");
    printf("  -s, --script PATH        Path to upgrade script\n\n");
    printf("Optional options:\n");
    printf("  -p, --port PORT          MQTT broker port (default: 1883)\n");
    printf("  -U, --username USER      MQTT username\n");
    printf("  -P, --password PASS      MQTT password\n");
    printf("  -t, --topic TOPIC        MQTT status topic\n");
    printf("  -m, --md5 MD5            Expected MD5 checksum of upgrade file\n");
    printf("  -h, --help               Show this help message\n\n");
    printf("Example:\n");
    printf("  %s -b 192.168.1.100 -u http://example.com/upgrade.zip \\\n", program_name);
    printf("     -s /root/ota_upgrade.sh -m abc123def456 -t device/upgrade/status\n");
}

int main(int argc, char *argv[])
{
    // 注册信号处理
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);

    // 默认参数
    char *mqtt_broker = NULL;
    int mqtt_port = 1883;
    char *mqtt_username = NULL;
    char *mqtt_password = NULL;
    char *status_topic = "device/upgrade/status";
    char *download_url = NULL;
    char *expected_md5 = NULL;
    char *upgrade_script = "/root/ota_upgrade.sh";

    // 定义命令行选项
    static struct option long_options[] = {
        {"broker", required_argument, 0, 'b'},
        {"port", required_argument, 0, 'p'},
        {"username", required_argument, 0, 'U'},
        {"password", required_argument, 0, 'P'},
        {"topic", required_argument, 0, 't'},
        {"url", required_argument, 0, 'u'},
        {"md5", required_argument, 0, 'm'},
        {"script", required_argument, 0, 's'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };

    // 解析命令行参数
    int opt;
    int option_index = 0;

    while ((opt = getopt_long(argc, argv, "b:p:U:P:t:u:m:s:h", long_options, &option_index)) != -1) {
        switch (opt) {
        case 'b':
            mqtt_broker = optarg;
            break;
        case 'p':
            mqtt_port = atoi(optarg);
            break;
        case 'U':
            mqtt_username = optarg;
            break;
        case 'P':
            mqtt_password = optarg;
            break;
        case 't':
            status_topic = optarg;
            break;
        case 'u':
            download_url = optarg;
            break;
        case 'm':
            expected_md5 = optarg;
            break;
        case 's':
            upgrade_script = optarg;
            break;
        case 'h':
            print_usage(argv[0]);
            return 0;
        default:
            print_usage(argv[0]);
            return 1;
        }
    }

    // 检查必需参数
    if (!mqtt_broker || !download_url) {
        fprintf(stderr, "Error: Missing required parameters\n\n");
        print_usage(argv[0]);
        return 1;
    }

    printf("Neuron Remote Upgrade Tool\n");
    printf("==========================\n");
    printf("MQTT Broker: %s:%d\n", mqtt_broker, mqtt_port);
    printf("Download URL: %s\n", download_url);
    printf("Upgrade Script: %s\n", upgrade_script);
    printf("Status Topic: %s\n", status_topic);
    if (expected_md5) {
        printf("Expected MD5: %s\n", expected_md5);
    }
    printf("\n");

    // 执行远程升级
    upgrade_result_t result = execute_remote_upgrade(
        mqtt_broker,
        mqtt_port,
        mqtt_username,
        mqtt_password,
        status_topic,
        download_url,
        expected_md5,
        upgrade_script
        );

    // 返回相应的退出码
    return result;
}
